package com.sudo.service.admin.service.impl;

import com.sudo.common.constant.UserConstant;
import com.sudo.common.utils.JsonUtil;
import com.sudo.dao.admin.entity.SysRole;
import com.sudo.dao.admin.entity.SysUserBehavior;
import com.sudo.dao.admin.mapper.SysRoleMapper;
import com.sudo.dao.admin.mapper.SysRoleMapperCustom;
import com.sudo.dao.admin.model.dto.OnlineUserDTO;
import com.sudo.dao.admin.model.vo.SysMenuButtonVO;
import com.sudo.dao.admin.model.vo.SysSimpleRoleButtonVO;
import com.sudo.starter.redis.component.RedisKeys;
import com.sudo.starter.redis.component.StringRedisUtil;
import com.sudo.service.admin.service.SysRedisAuthService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * @Author：DayDayUp
 * @Create：2023/3/22 10:23
 */
@Slf4j
@Service
public class SysRedisAuthServiceImpl implements SysRedisAuthService {
    @Resource
    public StringRedisUtil stringRedisUtil;

    @Override
    public void setRedisUserBehavior(SysUserBehavior sysUserBehavior) {
        stringRedisUtil.lLeftPush(RedisKeys.REDIS_USER_BEHAVIOR, JsonUtil.objectToJson(sysUserBehavior));
    }
    @Override
    public String getRedisUserBehavior() {
        return stringRedisUtil.lRightPop(RedisKeys.REDIS_USER_BEHAVIOR);
    }
    @Override
    public void setRedisUserExpire(String username) {
        String userTokenKey = RedisKeys.redisUserToken(username);
        stringRedisUtil.expire(userTokenKey, 7200, TimeUnit.SECONDS);
    }

    @Override
    public String getRedisUserTokenString(String username) {
        String userTokenKey = RedisKeys.redisUserToken(username);
        return stringRedisUtil.get(userTokenKey);
    }

    @Override
    public OnlineUserDTO getRedisUserToken(String username) {
        String userTokenKey = RedisKeys.redisUserToken(username);
        String userToken = stringRedisUtil.get(userTokenKey);
        return JsonUtil.jsonToPojo(userToken, OnlineUserDTO.class);
    }
    @Override
    public Set<String> getRedisUserTokenKey(String username) {
        String key;
        if (StringUtils.isBlank(username)) {
            key = RedisKeys.redisUserToken("*");
        }else {
            key = RedisKeys.redisUserToken(username);
        }
        return stringRedisUtil.keys(key);
    }

    @Override
    public void setRedisUserToken(String username, OnlineUserDTO onlineUserDTO) {
        stringRedisUtil.set(RedisKeys.redisUserToken(username),JsonUtil.objectToJson(onlineUserDTO),7200);
    }

    @Override
    public void delRedisUserToken(String username) {
        stringRedisUtil.delete(RedisKeys.redisUserToken(username));
    }

    @Override
    public void setRedisRoleStatus(String roleCode, String status) {
        stringRedisUtil.set(RedisKeys.redisRoleStatus(roleCode), status);
    }

    @Override
    public String getRedisRoleStatus(String roleCode) {
        return stringRedisUtil.get(RedisKeys.redisRoleStatus(roleCode));
    }

    @Override
    public void delRedisRoleStatus(String roleCode) {
        // 删除角色 redis_role_status
        stringRedisUtil.delete(RedisKeys.redisRoleStatus(roleCode));
    }

    @Override
    public void setRedisMenuButtonToRedis(String menuCode, String buttonCode) {
        stringRedisUtil.sAdd(RedisKeys.redisMenuButton(menuCode), buttonCode);
    }

    @Override
    public void delRedisMenuButtonFromRedis(String menuCode, String buttonCode) {
        String key = RedisKeys.redisMenuButton(menuCode);
        if (null == buttonCode) {
            stringRedisUtil.delete(key);
        }else {
            stringRedisUtil.sRemove(key, buttonCode);
        }
    }
    @Override
    public void setRedisRolePermissionToRedis(String roleCode, String menuCode, String buttonCode) {
        stringRedisUtil.sAdd(RedisKeys.redisRolePermission(roleCode,menuCode), buttonCode);
    }
    @Override
    public void setRedisRolePermissionToRedis(List<SysSimpleRoleButtonVO> sysSimpleRoleButtonVOList) {
        for (SysSimpleRoleButtonVO t: sysSimpleRoleButtonVOList){
            String key = RedisKeys.redisRolePermission(t.getRoleCode(), t.getMenuCode());
            if (Boolean.FALSE.equals(stringRedisUtil.hasKey(key))) {
                stringRedisUtil.sAdd(key, UserConstant.NONE);
            }else{
                stringRedisUtil.sAdd(key, t.getButtonCode());
            }
        }
    }
    @Override
    public void delRedisRolePermissionFromRedis(String roleCode, String menuCode, String buttonCode) {
        if (null != menuCode && null == buttonCode) {
            String key = RedisKeys.redisRolePermission(roleCode,menuCode);
            stringRedisUtil.delete(key);
        } else if (null == menuCode && buttonCode == null){
            String key = RedisKeys.redisRolePermission(roleCode, "*");
            stringRedisUtil.delete(stringRedisUtil.keys(key));
        }else {
            String key = RedisKeys.redisRolePermission(roleCode,menuCode);
            stringRedisUtil.sRemove(key, buttonCode);
        }
    }

    @Override
    public Set<String> getRedisAuthButton(String roleCode, String menuCode) {
        String key = RedisKeys.redisRolePermission(roleCode, menuCode);
        return stringRedisUtil.getMembers(key);
    }

    @Override
    public Set<String> getRedisMenuButton(String menuCode) {
        String key = RedisKeys.redisMenuButton(menuCode);
        return stringRedisUtil.getMembers(key);
    }

    @Override
    public boolean hasRoleMenuButton(String roleCode, String menuCode, String buttonCode){
        return stringRedisUtil.sIsMember(RedisKeys.redisRolePermission(roleCode,menuCode), buttonCode);
    }
    /**
     * 项目启动加载所有角色对应菜单的按钮权限(可用角色 可用菜单 可用按钮)
     */
    @Resource
    private SysRoleMapperCustom sysRoleMapperCustom;
    @Resource
    private SysRoleMapper sysRoleMapper;
    @Override
    @Transactional(propagation = Propagation.SUPPORTS, rollbackFor = Exception.class)
    public void onLoadAllRoleMenuButtonAuth(String roleCode, String menuCode) {
        //清空权限缓存
        if (null == roleCode) {
            stringRedisUtil.delete(stringRedisUtil.keys(RedisKeys.REDIS_ROLE_PERMISSION + ":*"));
        } else if (null != menuCode) {
            stringRedisUtil.delete(stringRedisUtil.keys(RedisKeys.redisRolePermission(roleCode, menuCode)));
        } else {
            stringRedisUtil.delete(stringRedisUtil.keys(RedisKeys.redisRolePermission(roleCode, "*")));
        }

        List<SysSimpleRoleButtonVO> sysSimpleRoleButtonVOList = sysRoleMapperCustom.getRoleMenuButtonAuth(roleCode,menuCode);

        for (SysSimpleRoleButtonVO sysSimpleRoleButtonVO : sysSimpleRoleButtonVOList) {
            String key = RedisKeys.redisRolePermission(sysSimpleRoleButtonVO.getRoleCode(), sysSimpleRoleButtonVO.getMenuCode());
            if (Boolean.FALSE.equals(stringRedisUtil.hasKey(key))) {
                stringRedisUtil.sAdd(key, "none");
            }
            if (StringUtils.isNotBlank(sysSimpleRoleButtonVO.getButtonCode())) {
                stringRedisUtil.sAdd(key, sysSimpleRoleButtonVO.getButtonCode());
            }
        }
    }

    @Override
    public void onLoadAllRoleStatus() {
        Example example = new Example(SysRole.class);
        example.selectProperties(SysRole.Field.roleCode, SysRole.Field.status);
        List<SysRole> sysRoleList = sysRoleMapper.selectByExample(example);
        for (SysRole role : sysRoleList) {
            stringRedisUtil.set(RedisKeys.redisRoleStatus(role.getRoleCode()),role.getStatus());
        }
    }

    /**
     * 加载所有可用菜单的可用按钮
     */
    @Override
    @Transactional(propagation = Propagation.SUPPORTS, rollbackFor = Exception.class)
    public void onLoadMenuButtonToRedis(String menuCode) {
        //清空菜单按钮缓存
        if (null == menuCode) {
            stringRedisUtil.delete(stringRedisUtil.keys(RedisKeys.redisMenuButton("*")));
        } else {
            stringRedisUtil.delete(stringRedisUtil.keys(RedisKeys.redisMenuButton(menuCode)));
        }
        List<SysMenuButtonVO> sysMenuButtonVOList = sysRoleMapperCustom.getMenuButtonByOn(menuCode);
        for (SysMenuButtonVO sysMenuButtonVO : sysMenuButtonVOList) {
            String key = RedisKeys.redisMenuButton(sysMenuButtonVO.getMenuCode());
            stringRedisUtil.sAdd(key, sysMenuButtonVO.getButtonCode());
        }
    }

    @Override
    public void setSysCpuLogByRealTime(String server, String value) {
        long len = stringRedisUtil.getListSize(RedisKeys.getCpuLogRedisRealTimeKey(server));
        if (len>=20){
            stringRedisUtil.lRightPop(server);
            setSysCpuLogByRealTime(server,value);
        }else {
            stringRedisUtil.lLeftPush(server,value);
        }
    }
    @Override
    public void setSysMemLogByRealTime(String server, String value) {
        long len = stringRedisUtil.getListSize(RedisKeys.getMemLogRedisRealTimeKey(server));
        if (len>=20){
            stringRedisUtil.lRightPop(server);
            setSysMemLogByRealTime(server,value);
        }else {
            stringRedisUtil.lLeftPush(server,value);
        }
    }

    @Override
    public void setSysCpuMemInfoByRealTime(String server, String value) {
        long len = stringRedisUtil.getListSize(RedisKeys.getMemCpuRedisRealTimeKey(server));
        if (len>=20){
            stringRedisUtil.lRightPop(server);
            setSysCpuMemInfoByRealTime(server,value);
        }else {
            stringRedisUtil.lLeftPush(server,value);
        }
    }

    @Override
    public String getRedisCpuLog(String serverNode) {
        return stringRedisUtil.lRightPop(RedisKeys.getCpuLogRedisKey(serverNode));
    }

    @Override
    public String getRedisMemLog(String serverNode) {
        return stringRedisUtil.lRightPop(RedisKeys.getMemLogRedisKey(serverNode));
    }

    @Override
    public List<String> getRedisCpuLogRealTime(String serverNode) {
        return stringRedisUtil.lRange(RedisKeys.getCpuLogRedisRealTimeKey(serverNode), 0, 0);
    }

    @Override
    public List<String> getRedisMemLogRealTime(String serverNode) {
        return stringRedisUtil.lRange(RedisKeys.getMemLogRedisRealTimeKey(serverNode), 0, 0);
    }

    @Override
    public void setRedisMemCpuRealTime(String serverNode, String data) {
        setSysCpuMemInfoByRealTime(RedisKeys.getMemCpuRedisRealTimeKey(serverNode),data);
    }

    @Override
    public List<String> getRedisMemCpuRealTime(String serverNode, int num) {
        return stringRedisUtil.lRange(RedisKeys.getMemCpuRedisRealTimeKey(serverNode), 0, num);
    }

}
